﻿#include <libdaq/backend/tcp_server/tcp_server.h>
#include <libdaq/backend/usb_server/usb_server.h>
#include "libdaq/device/DAQ216/DAQ216.h"
#include "libdaq/device/DAQ207/DAQ207.h"
#include "scroll_mode_thread/scroll_mode_thread.h"

#include <thread>
#include <iostream>

#ifdef WIN32
#pragma comment(linker, "/subsystem:console /ENTRY:mainCRTStartup")
#endif

// 定义回调函数，用于打印各个通道的数据长度
void data_callback(const std::vector<std::vector<float>> &data) {
    std::cout << "收到数据：" << std::endl;
    for (size_t i = 0; i < data.size(); i++) {
        std::cout << "通道 " << i << " 数据长度: " << data[i].size() << std::endl;
    }
    std::cout << "------------------------" << std::endl;
}

int main(int argc, char *argv[])
{
    std::unique_ptr<libdaq::backend::LockzhinerUSBServer> usb_server_; // USB服务器

    std::shared_ptr<libdaq::device::DAQ216> base_device_
        = std::make_shared<libdaq::device::DAQ216>(); // 设备指针

    // Create LockzhinerUSBServer
    const auto usb_option = libdaq::device::DAQ216::GetUSBOption();
    usb_server_ = std::make_unique<libdaq::backend::LockzhinerUSBServer>(usb_option);

    // 1.开始搜索USB设备
    // 直到寻找到为止
    uint8_t bus = 0, device = 0;
    while(bus == 0 && device == 0){
        usb_server_->StartSearch();
        const auto bus_numbers = usb_server_->GetBusNumbers();
        std::cout << "bus size = " << bus_numbers.size() << std::endl;
        for (auto &bus_number: bus_numbers) {
            bus = bus_number;
            const auto device_addresses = usb_server_->GetDeviceAddresses(bus_number);
            std::cout << "device_addresses size = " << device_addresses.size() << std::endl;
            for (auto &device_address: device_addresses) {
                device = device_address;
            }
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    std::cout << "bus = " << (int)bus << " device = " << (int)device << std::endl;

    auto socket = usb_server_->GetClient(bus, device);
    base_device_->UseBackend(socket);

    // 2.初始化设备
    if (!base_device_->InitializeDevice()) {
        printf("初始化设备失败，请检查配置参数是否存在错误");
        return -1;
    }

    // 3.连接设备
    if (!base_device_->ConnectedDevice()) {
        printf("发送连接设备命令失败");
        return -1;
    }


    // 设备返回数据需要时间 1s后再判断
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    if (!socket->is_initialized() || !socket->is_opened()){
        std::cout << "socket connect failed";
        return -1;
    }

    // 4.下发采集配置

    // 采样率 1M
    if (!base_device_->ConfigADCSampleRate(libdaq::device::LockzhinerADCSampleRate::ADCSampleRate_1_M)) {
        printf("采样率配置失败");
    }
    // 电压量程 1V
    if (!base_device_->ConfigADCVoltage(libdaq::device::LockzhinerADCVoltage::ADCVoltage_1_V)) {
        printf("电压量程配置失败");
    }
    // 4通道使能
    if (!base_device_->ConfigADCChannel(0b00001111)) {
        printf("ADC4通道配置失败");
    }
    // 触发电平 0mv
    uint32_t level=0;
    // 滚动模式 
    auto type = static_cast<libdaq::device::LockzhinerADCTriggerType>(libdaq::device::LockzhinerADCTriggerType::Normal);
    // 其他参数会被忽略
    auto mode = static_cast<libdaq::device::LockzhinerADCTriggerMode>(libdaq::device::LockzhinerADCTriggerMode::Common);
    auto channel = static_cast<libdaq::device::LockzhinerADCChannel>(libdaq::device::LockzhinerADCChannel::ADCChannelAINNone);
    if (!base_device_->ConfigADCTrigger(type, mode, channel, level)) {
        printf("DAQ控制器配置ADC触发失败");
    }

    // 长度 4920个点
    if (!base_device_->ConfigADCTriggerLength(4920)) {
        printf("触发长度配置失败");
    }
    // 超时 100ms
    if (!base_device_->ConfigTriggerTimeout(100)) {
        printf("超时时间配置失败");
    }

    if(!base_device_->StopADCCollection()){
        printf("stop ADC采集失败\n");
        return -1;
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    // 开始采集
    if (!base_device_->StartADCCollection())
    {
        printf("启动ADC采集失败\n");
        return -1;
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    // 软件触发 单次触发需要下发该命令才会数据上来
    if (!base_device_->ConfigADCTriggerSource(static_cast<uint8_t>(libdaq::device::DAQADCTriggerSource::TriggerSourceSoftware)))
    {
        printf("软件触发失败");
        return -1;
    }


    // 创建线程读取数据
    std::unique_ptr<ScrollModeADCThread> scroll_mode_adc_thread_ = std::make_unique<ScrollModeADCThread>(base_device_);
    scroll_mode_adc_thread_->setDataCallback(data_callback);
    scroll_mode_adc_thread_->start();

    while(scroll_mode_adc_thread_ && scroll_mode_adc_thread_->thread_is_running()){
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    scroll_mode_adc_thread_->quit();

    if(!base_device_->StopADCCollection()){
        printf("stop ADC采集失败\n");
        return -1;
    }

    return 0;
}
